<<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0, user-scalable=no">
    <title>防抖的函数实现</title>
</head>
  <body>
    <button id="btn">点击</button>
    <script>
      var oBtn = document.getElementById('btn')
      // oBtn.onclick = function() {
      //   console.log('点击了')
      // }
      /*
      *  handle：最终需要执行的事件监听，
      *  wait: 时间触发之后开始执行的时间. 
      *  immediate: 控制执行的第一次还是最后一次， false 为执行最后一次
      */ 
      function myDebounce(handle, wait, immediate) {
         // 参数类型判断及默认值处理
          if (typeof handle !== 'function') throw new Error('handle must be an function')
          if (typeof wait === 'undefined') wait = 300
          if (typeof wait === 'boolean') {
            immediate = wait
            wait = 300
          }
          if (typeof immediate !== 'boolean') immediate = false
          // 所谓的防抖效果我们想要实现的就是有一个“人”，可以管理handle的执行次数
          // 如果我们想要执行最后一次，那就意味着无论我们当前点了多少次，前面的 N-1次都无效
          let timer = null // 返回结果
          return function proxy(...args) {
            let self = this // 保存this
            let init = immediate && !timer 
            clearTimeout(timer) // 点击第二次的时候，清除timer，取最后一次的点击
            // 如果timer不为null，执行下面语句
            timer = setTimeout(() => {
              timer = null
              !immediate ? handle.call(self, ...args): null // 改变this的指向；
            },wait) 
            // 如果当前传递进来的true，表示需要立即执行
            // 如果想要实现只在第一次追星，那么可以添加timerw为null作为判断
            // 因为只要timer为Null，就意味着没有第二次点击了
            init ? handle.call(self, ...args): null
          }
        }
      // 定义事件执行函数
      function btnCLick (ev) {
        console.log('点击了', this, ev)
      }
      // btnCLick
      oBtn.onclick = myDebounce(btnCLick, 200, false)
      // oBtn.onclick = btnCLick() // this ev
    </script>
  </body>
</html>
